package com.ruoyi.service.impl;

import cn.hutool.json.JSONUtil;
import com.ruoyi.domain.PaymentRequest;
import com.ruoyi.service.PaymentService;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.Event;
import com.stripe.model.PaymentIntent;
import com.stripe.model.PaymentMethod;
import com.stripe.model.Refund;
import com.stripe.model.billingportal.Session;
import com.stripe.net.Webhook;
import com.stripe.param.PaymentIntentCreateParams;
import com.stripe.param.PaymentMethodCreateParams;
import com.stripe.param.RefundCreateParams;
import com.stripe.param.billingportal.SessionCreateParams;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

@Service
@Slf4j
public class PaymentServiceImpl implements PaymentService {

    @Value("${stripe.api-key}")
    private String stripeApiKey;

    @Value("${stripe.webhook-secret}")
    private String stripeWebhookSecret;

    /**
     * 初始化 Stripe API 密钥
     */
    @PostConstruct
    public void init() {
        Stripe.apiKey = this.stripeApiKey;
        log.info("Stripe API key initialized");
    }


    /**
     * 创建支付意图
     *
     * @param currency       货币类型（如 "usd", "cny"）
     * @param amount         支付金额（单位为最小货币单位：分）
     * @param paymentRequest 支付请求参数对象
     * @return 客户端秘钥 (clientSecret)
     * @throws StripeException Stripe SDK 异常
     */
    public String createPaymentIntent(String currency, long amount, String paymentMethodType,PaymentRequest paymentRequest) throws StripeException {

        // 创建自定义元数据，存储额外的业务信息
        PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
                .setAmount(amount)
                .setCurrency(currency)
                .putMetadata("orderId", paymentRequest.getOrderId())
                .putMetadata("userId", paymentRequest.getUserId())
                .putMetadata("orderType", paymentRequest.getOrderType())
                .putMetadata("packageId", paymentRequest.getPackageId())
                .putMetadata("packageName", paymentRequest.getPackageName())
//                .setConfirm(true)
//                .addPaymentMethodType(paymentMethodType).build();

                .setAutomaticPaymentMethods(PaymentIntentCreateParams.AutomaticPaymentMethods.builder().setEnabled(true)
                        .setAllowRedirects(PaymentIntentCreateParams.AutomaticPaymentMethods.AllowRedirects.NEVER).build())
                .build();
        PaymentIntent paymentIntent = PaymentIntent.create(params);

        log.info("Created PaymentIntent", JSONUtil.toJsonStr(paymentIntent));
        return paymentIntent.getClientSecret();
    }

    /**
     * 创建并确认支付意图
     *
     * @param currency          货币类型（如 "usd"）
     * @param amount            支付金额（以最小单位表示，例如美分）
     * @param paymentMethodType 支付方式类型（如 "card"）
     * @param paymentDetails    支付方式详细信息
     * @param paymentRequest    支付请求对象
     * @return 支付意图的客户端秘钥
     * @throws StripeException 如果 Stripe API 调用失败
     */
    @Override

    public String createAndConfirmPaymentIntent(String currency, long amount, String paymentMethodType, Map<String, Object> paymentDetails, PaymentRequest paymentRequest) throws StripeException {
        // 创建支付方法
        String paymentMethodId = createPaymentMethod(paymentMethodType, paymentDetails);

        // 创建支付意图
        PaymentIntent paymentIntent = createPaymentIntentWithPaymentMethod(currency, amount, paymentMethodId, paymentRequest);

        // 返回客户端秘钥
        return paymentIntent.getClientSecret();
    }

    /**
     * 创建支付方法
     *
     * @param type    支付方式类型（如 "card"）
     * @param details 支付方式详细信息
     * @return 创建的支付方法 ID
     * @throws StripeException 如果 Stripe API 调用失败
     */
    private String createPaymentMethod(String type, Map<String, Object> details) throws StripeException {
        PaymentMethodCreateParams params;

        switch (type.toLowerCase()) {
            case "card":
                // 构建信用卡支付方式参数
                params = PaymentMethodCreateParams.builder()
                        .setType(PaymentMethodCreateParams.Type.CARD)
                        .setCard(PaymentMethodCreateParams.CardDetails.builder()
                                .setNumber((String) details.get("cardNumber"))
                                .setExpMonth(Long.valueOf((Integer) details.get("expMonth")))
                                .setExpYear(Long.valueOf((Integer) details.get("expYear")))
                                .setCvc((String) details.get("cvc"))
                                .build()).
                        build();
                break;

            case "sepa_debit":
                // 构建 SEPA Direct Debit 支付方式参数
                params = PaymentMethodCreateParams.builder().setType(PaymentMethodCreateParams.Type.SEPA_DEBIT).setSepaDebit(PaymentMethodCreateParams.SepaDebit.builder().setIban((String) details.get("iban")).build()).build();
                break;

            case "ideal":
                // 构建 iDEAL 支付方式参数
                String bankCode = (String) details.get("bank");
                params = PaymentMethodCreateParams.builder().setType(PaymentMethodCreateParams.Type.IDEAL).setIdeal(PaymentMethodCreateParams.Ideal.builder().setBank(PaymentMethodCreateParams.Ideal.Bank.valueOf(bankCode.toUpperCase())).build()).build();
                break;

            case "sofort":
                // 构建 Sofort 支付方式参数
                String country = (String) details.get("country");
                params = PaymentMethodCreateParams.builder().setType(PaymentMethodCreateParams.Type.SOFORT).setSofort(PaymentMethodCreateParams.Sofort.builder().setCountry(PaymentMethodCreateParams.Sofort.Country.valueOf(country.toUpperCase())).build()).build();
                break;

            case "wechat_pay":
                // 构建微信支付参数
                params = PaymentMethodCreateParams.builder()
                        .setType(PaymentMethodCreateParams.Type.WECHAT_PAY)
                        // 微信支付不需要额外的参数
                        .build();
                break;

            case "alipay":
                // 构建支付宝支付参数
                params = PaymentMethodCreateParams.builder()
                        .setType(PaymentMethodCreateParams.Type.ALIPAY)
                        // 支付宝不需要额外的参数
                        .build();
                break;
            case "paypal":
                throw new UnsupportedOperationException("Payment method " + type + " requires integration with PaymentIntent or Checkout.");

            default:
                throw new IllegalArgumentException("Unsupported payment method type: " + type);
        }

        // 创建支付方法
        PaymentMethod paymentMethod = PaymentMethod.create(params);

        // 返回支付方法 ID
        return paymentMethod.getId();
    }

    /**
     * 创建支付意图并指定支付方法
     *
     * @param currency        货币类型
     * @param amount          支付金额
     * @param paymentMethodId 支付方法 ID
     * @param paymentRequest  支付请求对象
     * @return 创建的支付意图对象
     * @throws StripeException 如果 Stripe API 调用失败
     */
    private PaymentIntent createPaymentIntentWithPaymentMethod(String currency, long amount, String paymentMethodId, PaymentRequest paymentRequest) throws StripeException {
        PaymentIntentCreateParams.Builder paramsBuilder = PaymentIntentCreateParams.builder()
                .setAmount(amount)
                .setCurrency(currency)
                .setPaymentMethod(paymentMethodId)
                .setConfirm(true)
                .setAutomaticPaymentMethods(PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
                        .setEnabled(true)
                        .setAllowRedirects(PaymentIntentCreateParams.AutomaticPaymentMethods.AllowRedirects.NEVER)
                        .build());

        // 设置额外的元数据
        paramsBuilder.putMetadata("orderId", paymentRequest.getOrderId());
        paramsBuilder.putMetadata("userId", paymentRequest.getUserId());
        paramsBuilder.putMetadata("orderType", paymentRequest.getOrderType());
        paramsBuilder.putMetadata("packageId", paymentRequest.getPackageId());
        paramsBuilder.putMetadata("packageName", paymentRequest.getPackageName());
        // 处理额外支付请求参数
        if (paymentRequest.getDescription() != null) {
            paramsBuilder.setDescription(paymentRequest.getDescription());
        }
        if (paymentRequest.getCustomerId() != null) {
            paramsBuilder.setCustomer(paymentRequest.getCustomerId());
        }


        // 创建支付意图
        return PaymentIntent.create(paramsBuilder.build());
    }

    public String createPaymentIntentWithWeChatPay(String currency, long amount, String appId) throws StripeException {
        PaymentIntentCreateParams params =
                PaymentIntentCreateParams.builder()
                        .addPaymentMethodType("wechat_pay")
                        .setAmount(1099L)
                        .setCurrency("sgd")
                        .build();

        PaymentIntent paymentIntent = PaymentIntent.create(params);
        return paymentIntent.getClientSecret();
    }

    public String createPaymentIntentWithAlipay(String currency, long amount) throws StripeException {

        // 创建PaymentIntent参数
        PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
                .setAmount(amount) // 支付金额，单位为最小货币单位（例如：人民币分）
                .setCurrency(currency) // 货币代码，支付宝支持CNY
                .addPaymentMethodType("alipay") // 添加支付宝支付
                .build();

        // 创建PaymentIntent
        PaymentIntent paymentIntent = PaymentIntent.create(params);

        // 返回PaymentIntent客户端秘钥
        return paymentIntent.getClientSecret();
    }


    /**
     * 创建退款
     *
     * @param paymentIntentId 支付意图的 ID
     * @param amount          退款金额（单位为最小货币单位：分），传 null 全额退款
     * @return Refund 对象
     * @throws StripeException Stripe SDK 异常
     */
    public Refund createRefund(String paymentIntentId, Long amount) throws StripeException {
        RefundCreateParams.Builder paramsBuilder = RefundCreateParams.builder().setPaymentIntent(paymentIntentId);

        if (amount != null) {
            paramsBuilder.setAmount(amount); // 部分退款金额
        }

        RefundCreateParams params = paramsBuilder.build();
        return Refund.create(params);
    }

    /**
     * 处理 Stripe Webhook 事件
     *
     * @param request HTTP 请求对象
     * @return Webhook 处理结果
     */
    public String handleStripeWebhook(HttpServletRequest request) {
        log.info("进入webhook:{}", JSONUtil.toJsonStr(request));
        String payload;
        try {
            // 读取 Stripe Webhook 发送的数据
            StringBuilder sb = new StringBuilder();
            BufferedReader reader = request.getReader();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            payload = sb.toString();
            log.info("payload返回信息：{}", JSONUtil.toJsonStr(payload));
        } catch (IOException e) {
            log.error("Webhook error while reading payload", e);
            return "Webhook Error: Failed to read payload";
        }

        // 验证 Webhook 签名
        String sigHeader = request.getHeader("Stripe-Signature");
        Event event;
        try {
            event = Webhook.constructEvent(payload, sigHeader, stripeWebhookSecret);
            log.info("event:{}", JSONUtil.toJsonStr(event));
        } catch (Exception e) {
            log.error("Webhook error while validating signature", e);
            return "Webhook Error: Invalid signature";
        }

        // 处理不同事件类型
        switch (event.getType()) {
            case "payment_intent.succeeded":
                return handlePaymentIntentSucceeded(event);
            case "payment_intent.payment_failed":
                return handlePaymentIntentFailed(event);
            case "charge.refunded":
                return handleChargeRefunded(event);
            default:
                log.info("Unhandled event type: {}", event.getType());
                return "Unhandled event type";
        }
    }

    // 处理 PaymentIntent 成功支付
    private String handlePaymentIntentSucceeded(Event event) {
        PaymentIntent paymentIntent = (PaymentIntent) event.getDataObjectDeserializer().getObject().orElse(null);
        if (paymentIntent != null) {
            log.info("Payment succeeded: {}", paymentIntent.getId());
            // 执行自定义业务逻辑，例如更新订单状态
            return "Payment Intent succeeded";
        }
        return "Failed to parse payment intent";
    }

    // 处理 PaymentIntent 支付失败
    private String handlePaymentIntentFailed(Event event) {
        log.warn("Payment failed: {}", event.getId());
        // 执行支付失败处理
        return "Payment Intent failed";
    }

    // 处理退款成功
    private String handleChargeRefunded(Event event) {
        Refund refund = (Refund) event.getDataObjectDeserializer().getObject().orElse(null);
        if (refund != null) {
            log.info("Refund succeeded: {}", refund.getId());
            // 执行退款相关逻辑
            return "Refund succeeded";
        }
        return "Failed to parse refund";
    }

/*    public static void main(String[] args) {
        try {
            createPaymentMethod creator = new createPaymentMethod();

            // 示例测试：创建信用卡支付方式
            Map<String, Object> cardDetails = Map.of("cardNumber", "4242424242424242", "expMonth", 12, "expYear", 2025, "cvc", "123");
            String paymentMethodId = creator.createPaymentMethod("card", cardDetails);
            System.out.println("Created Payment Method ID: " + paymentMethodId);

            // 示例测试：创建 SEPA Direct Debit 支付方式
            Map<String, Object> sepaDetails = Map.of("iban", "DE89370400440532013000");
            paymentMethodId = creator.createPaymentMethod("sepa_debit", sepaDetails);
            System.out.println("Created Payment Method ID: " + paymentMethodId);

        } catch (StripeException e) {
            e.printStackTrace();
        }
    }*/
}
